package com.dq.exception;

import com.dq.exception.customException.AdminException;
import com.dq.exception.customException.ApiException;
import com.dq.exception.customException.DqRuntimeException;
import com.dq.vo.Vo;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.authz.AuthorizationException;
import org.apache.shiro.authz.UnauthenticatedException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.http.HttpStatus;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import javax.validation.ValidationException;
import java.util.Set;

/**
 * 异常统一处理类
 * @author ----
 */
@RestControllerAdvice
public class AppExceptionHandler {

    private static final Logger LOGGER = LoggerFactory.getLogger(AppExceptionHandler.class);

    /**
     * 自定义注解验证异常处理类
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public Vo handleMethodArgumentNotValidException(MethodArgumentNotValidException e) {
        LOGGER.error(e.getMessage(), e);

        String message = e.getMessage();
        if (e.getBindingResult().getFieldError() != null) {
            message = e.getBindingResult().getFieldError().getDefaultMessage();
        }
        return new Vo(HttpStatus.BAD_REQUEST, message);
    }
    /**
     * 参数校验异常, @notnull
     */
    @ExceptionHandler(ConstraintViolationException.class)
    public Vo constraintViolationException(ConstraintViolationException e) {
        LOGGER.error(e.getMessage(), e);

        StringBuilder message = new StringBuilder();
        Set<ConstraintViolation<?>> violations = e.getConstraintViolations();
        for (ConstraintViolation<?> violation : violations) {
            if(StringUtils.isNotBlank(message)) {
                message.append(", <br/>").append(violation.getMessage());
            }else {
                message.append(violation.getMessage());
            }
        }
        return new Vo(HttpStatus.BAD_REQUEST, message.toString());
    }
    @ExceptionHandler({ValidationException.class})
    public Object process(ValidationException e) {
        LOGGER.error(e.getMessage(), e);
        return new Vo(HttpStatus.BAD_REQUEST, e.getMessage());
    }

    @ExceptionHandler(AuthorizationException.class)
    public Vo handleAuthorizationException(AuthorizationException e) {
        LOGGER.error(e.getMessage(), e);
        return new Vo(HttpStatus.UNAUTHORIZED, "没有权限，请联系管理员授权");
    }
    @ExceptionHandler(UnauthenticatedException.class)
    public Vo handleAuthorizationException(UnauthenticatedException e) {
        LOGGER.error(e.getMessage(), e);
        return new Vo(HttpStatus.UNAUTHORIZED, "请先登陆");
    }

    @ExceptionHandler(DuplicateKeyException.class)
    public Vo handleDuplicateKeyException(DuplicateKeyException e) {
        LOGGER.error(e.getMessage(), e);
        return new Vo(HttpStatus.BAD_REQUEST, "数据库中已存在该记录");
    }

    /**
     * 后台管理 自定义异常类
     */
    @ExceptionHandler(AdminException.class)
    public Vo e(AdminException e) {
        LOGGER.error(e.getMessage(), e);
        return new Vo(HttpStatus.BAD_REQUEST, e.getMessage());
    }
    /**
     * api接口管理 自定义异常类
     */
    @ExceptionHandler(ApiException.class)
    public Vo apiException(ApiException e) {
        LOGGER.error(e.getMessage(), e);
        return new Vo(e.getErrno(), e.getMessage());
    }
    /**
     * 后台/api接口管理 自定义异常类
     */
    @ExceptionHandler(DqRuntimeException.class)
    public Vo handleDqRuntimeException(DqRuntimeException e) {
        LOGGER.error(e.getMessage(), e);
        return new Vo(HttpStatus.UNAUTHORIZED, e.getMessage());
    }

    @ExceptionHandler(HttpRequestMethodNotSupportedException.class)
    public Vo handleHttpRequestMethodNotSupportedException(HttpRequestMethodNotSupportedException e) {
        LOGGER.error(e.getMessage(), e);
        return new Vo(HttpStatus.NOT_ACCEPTABLE, "不支持该方法");
    }

    @ExceptionHandler(Exception.class)
    public Vo handleException(Exception e) {
        LOGGER.error(e.getMessage(), e);
        return new Vo(HttpStatus.BAD_REQUEST, e.getMessage());
    }

}
